package com.liuyc.lib.ui.xrecycleview

import android.content.Context
import android.net.ConnectivityManager
import android.util.AttributeSet
import android.util.SparseArray
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.liuyc.lib.ui.xrecycleview.CustomBaseRefreshHeader.Companion.STATE_REFRESHING

class CustomRecyclerView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {
    private var mLoadingListener: LoadingListener? = null
    private var mCustomWrapAdapter: CustomWrapAdapter? = null
    private val mHeaderViews: SparseArray<View>? = SparseArray()
    private val mFootViews: SparseArray<View>? = SparseArray()
    private var pullRefreshEnabled = true
    private var loadingMoreEnabled = true
    private var mRefreshHeader: CustomRefreshHeader? = null
    private var mRefreshFooter: CustomLoadingMoreFooter? = null
    private var isLoadingData = false
    var previousTotal = 0
    var isnomore = false
    private var mLastY = -1f
    private val DRAG_RATE = 1.75f

    // 是否是额外添加FooterView
    private var isOther = false

    init {
        init(context)
    }

    fun getRefreshFooter(): CustomLoadingMoreFooter {
        return mRefreshFooter!!
    }

    private fun init(context: Context) {
        if (pullRefreshEnabled) {
            val refreshHeader = CustomRefreshHeader(context)
            mHeaderViews!!.put(0, refreshHeader)
            mRefreshHeader = refreshHeader
        }
        mRefreshFooter = CustomLoadingMoreFooter(context)
        addFootView(mRefreshFooter as CustomLoadingMoreFooter, false)
        mFootViews!![0].visibility = GONE
    }

    /**
     * 改为公有。供外添加view使用,使用标识
     * 注意：使用后不能使用 上拉加载，否则添加无效
     * 使用时 isOther 传入 true，然后调用 noMoreLoading即可。
     */
    fun addFootView(view: View, isOther: Boolean) {
        mFootViews!!.clear()
        mFootViews.put(0, view)
        this.isOther = isOther
    }

    /**
     * 相当于加一个空白头布局：
     * 只有一个目的：为了滚动条显示在最顶端
     * 因为默认加了刷新头布局，不处理滚动条会下移。
     * 和 setPullRefreshEnabled(false) 一块儿使用
     * 使用下拉头时，此方法不应被使用！
     */
    fun clearHeader() {
        mHeaderViews!!.clear()
        val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1)
        val view = View(context)
        view.layoutParams = params
        mHeaderViews.put(0, view)
    }

    fun addHeaderView(view: View) {
        if (pullRefreshEnabled && mHeaderViews!![0] !is CustomRefreshHeader) {
            val refreshHeader = CustomRefreshHeader(context)
            mHeaderViews!!.put(0, refreshHeader)
            mRefreshHeader = refreshHeader
        }
        mHeaderViews!!.put(mHeaderViews.size(), view)
    }

    private fun loadMoreComplete() {
        isLoadingData = false
        val footView = mFootViews!![0]
        if (previousTotal <= layoutManager!!.itemCount) {
            if (footView is CustomLoadingMoreFooter) {
                footView.setState(CustomLoadingMoreFooter.STATE_COMPLETE)
            } else {
                footView.visibility = GONE
            }
        } else {
            if (footView is CustomLoadingMoreFooter) {
                footView.setState(CustomLoadingMoreFooter.STATE_NOMORE)
            } else {
                footView.visibility = GONE
            }
            isnomore = true
        }
        previousTotal = layoutManager!!.itemCount
    }

    fun noMoreLoading() {
        isLoadingData = false
        val footView = mFootViews!![0]
        isnomore = true
        if (footView is CustomLoadingMoreFooter) {
            footView.setState(CustomLoadingMoreFooter.STATE_NOMORE)
        } else {
            footView.visibility = GONE
        }
        // 额外添加的footView
        if (isOther) {
            footView.visibility = VISIBLE
        }
    }

    fun refreshComplete() {
        //  mRefreshHeader.refreshComplate();
        if (isLoadingData) {
            loadMoreComplete()
        } else {
            mRefreshHeader!!.refreshComplete()
        }
    }

    override fun setAdapter(adapter: Adapter<RecyclerView.ViewHolder>?) {
        mCustomWrapAdapter = CustomWrapAdapter(mHeaderViews!!, mFootViews!!, adapter)
        super.setAdapter(mCustomWrapAdapter)
        adapter!!.registerAdapterDataObserver(mDataObserver)
    }

    override fun onScrollStateChanged(state: Int) {
        super.onScrollStateChanged(state)
        if (state == SCROLL_STATE_IDLE && mLoadingListener != null && !isLoadingData && loadingMoreEnabled) {
            val layoutManager = layoutManager
            val lastVisibleItemPosition: Int
            lastVisibleItemPosition = if (layoutManager is GridLayoutManager) {
                (layoutManager as GridLayoutManager?)!!.findLastVisibleItemPosition()
            } else if (layoutManager is StaggeredGridLayoutManager) {
                val into = IntArray((layoutManager as StaggeredGridLayoutManager?)!!.getSpanCount())
                (layoutManager as StaggeredGridLayoutManager?)!!.findLastVisibleItemPositions(into)
                findMax(into)
            } else {
                (layoutManager as LinearLayoutManager?)!!.findLastVisibleItemPosition()
            }
            if (layoutManager!!.childCount > 0 && lastVisibleItemPosition >= layoutManager.itemCount - 1 && layoutManager.itemCount > layoutManager.childCount && !isnomore
                    && mRefreshHeader!!.getState() < STATE_REFRESHING) {
                val footView = mFootViews!![0]
                isLoadingData = true
                if (footView != null) {
                    if (footView is CustomLoadingMoreFooter) {
                        footView.setState(CustomLoadingMoreFooter.STATE_LOADING)
                    } else {
                        footView.visibility = VISIBLE
                    }
                }
                if (isNetWorkConnected(context)) {
                    mLoadingListener!!.onLoadMore()
                } else {
                    postDelayed({ mLoadingListener!!.onLoadMore() }, 1000)
                }
            }
        }
    }

    override fun onTouchEvent(ev: MotionEvent): Boolean {
        if (mLastY == -1f) {
            mLastY = ev.rawY
        }
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> mLastY = ev.rawY
            MotionEvent.ACTION_MOVE -> {
                val deltaY = ev.rawY - mLastY
                mLastY = ev.rawY
                if (isOnTop() && pullRefreshEnabled) {
                    mRefreshHeader!!.onMove(deltaY / DRAG_RATE)
                    if (mRefreshHeader!!.getVisiableHeight() > 0 && mRefreshHeader!!.getState() < STATE_REFRESHING) {
                        return false
                    }
                }
            }
            else -> {
                mLastY = -1f // reset
                if (isOnTop() && pullRefreshEnabled) {
                    if (mRefreshHeader!!.releaseAction()) {
                        if (mLoadingListener != null) {
                            mLoadingListener!!.onRefresh()
                            isnomore = false
                            previousTotal = 0
                            val footView = mFootViews!![0]
                            if (footView is CustomLoadingMoreFooter) {
                                if (footView.getVisibility() != GONE) {
                                    footView.setVisibility(GONE)
                                }
                            }
                        }
                    }
                }
            }
        }
        return super.onTouchEvent(ev)
    }

    private fun findMax(lastPositions: IntArray): Int {
        var max = lastPositions[0]
        for (value in lastPositions) {
            if (value > max) {
                max = value
            }
        }
        return max
    }

    private fun findMin(firstPositions: IntArray): Int {
        var min = firstPositions[0]
        for (value in firstPositions) {
            if (value < min) {
                min = value
            }
        }
        return min
    }

    fun isOnTop(): Boolean {
        if (mHeaderViews == null || mHeaderViews.size() == 0) {
            return false
        }
        val view = mHeaderViews[0]
        return if (view.parent != null) {
            true
        } else {
            false
        }
    }

    private val mDataObserver: AdapterDataObserver = object : AdapterDataObserver() {
        override fun onChanged() {
            mCustomWrapAdapter!!.notifyDataSetChanged()
        }

        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
            mCustomWrapAdapter!!.notifyItemRangeInserted(positionStart, itemCount)
        }

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
            mCustomWrapAdapter!!.notifyItemRangeChanged(positionStart, itemCount)
        }

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
            mCustomWrapAdapter!!.notifyItemRangeChanged(positionStart, itemCount, payload)
        }

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
            mCustomWrapAdapter!!.notifyItemRangeRemoved(positionStart, itemCount)
        }

        override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
            mCustomWrapAdapter!!.notifyItemMoved(fromPosition, toPosition)
        }
    }


    fun setLoadingListener(listener: LoadingListener?) {
        mLoadingListener = listener
    }

    fun setPullRefreshEnabled(pullRefreshEnabled: Boolean) {
        this.pullRefreshEnabled = pullRefreshEnabled
    }

    fun setLoadingMoreEnabled(loadingMoreEnabled: Boolean) {
        this.loadingMoreEnabled = loadingMoreEnabled
        if (!loadingMoreEnabled) {
            mFootViews?.remove(0)
        } else {
            if (mFootViews != null) {
                val footView = CustomLoadingMoreFooter(context)
                addFootView(footView, false)
            }
        }
    }


    fun setLoadMoreGone() {
        if (mFootViews == null) {
            return
        }
        val footView = mFootViews[0]
        if (footView != null && footView is CustomLoadingMoreFooter) {
            mFootViews.remove(0)
        }
    }

    fun setLoadMoreEvent() {
        if (mFootViews == null) {
            return
        }
        val footView = mFootViews[0]

    }

    interface LoadingListener {
        fun onRefresh()
        fun onLoadMore()
    }

    /**
     * 检测网络是否可用
     *
     * @param context
     * @return
     */
    fun isNetWorkConnected(context: Context?): Boolean {
        if (context != null) {
            val mConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val mNetworkInfo = mConnectivityManager.activeNetworkInfo
            if (mNetworkInfo != null) {
                return mNetworkInfo.isConnected
            }
        }
        return false
    }

    fun reset() {
        isnomore = false
        previousTotal = 0
        val footView = mFootViews!![0]
        if (footView is CustomLoadingMoreFooter) {
            footView.reSet()
        }
    }

    /**
     * 是否在刷新数据
     */
    fun isLoadingData(): Boolean {
        return isLoadingData
    }

}